package com.cctc.juc.source.Bitc.Ecas;
/**
 * 【CAS（Compare And Swap，比较与交换）算法】
 * 简述：CAS 算法是一种有名的 “无锁（乐观锁）编程” 算法，即在不使用锁的情况下（非阻塞方式）实现多线程之间共享资源的同步（互斥）操作。
 * 1. CAS 算法原理：
 * - 需要更新的内存值 V；
 * - 待更新的旧值 A；
 * - 更新后的新值 B；
 * 当且仅当（比较） A == V 时，CAS 才会（交换）使用新值 B 更新内存值 V，否则不会执行任何操作。
 * 该过程（比较与交换）是 CPU 指令级别的原子操作，并且处于用户态，单次操作开销非常小。
 * 但一般情况下，为了达到目的，我们会在用户态进行 “自旋”，即不断重试，直到操作（更新）成功。
 * 2. Unsafe 类：
 * CAS 算法在操作系统层面对应于一条 CPU 原子指令（cmpxchg 指令），Java 通过 JNI 将其（C++ 代码）封装成了一个 Unsafe 类，提供给 Java 应用层进行使用。
 * 下面给出使用 Unsafe 类实现无锁（乐观锁）编程的大致步骤：
 * 1）获取 Unsafe 实例；
 * 2）调用 Unsafe 提供的字段（属性）偏移量方法，获取字段（属性）在内存中（相对于对象头）的偏移地址；
 * 3）调用 Unsafe 提供的 CAS 方法，完成 CAS 原子操作。
 * 4）若 3）操作失败，“自旋” 重复执行 2）、3），直到 CAS 操作成功。
 * 3. CAS 算法（乐观锁）的弊端及解决办法：
 * 1）ABA 问题；
 * - 解决办法：MVVC 多版本控制（ABA -> A1B1A2），可以使用 JUC 提供的两个原子类 AtomicStampedReference [原子印戳引用类]、AtomicMarkableReference [原子标记引用类] 进行多版本操作控制。
 * 2）每次只能保证一个共享变量的原子操作；
 * - 解决办法：多变量组合原子操作，可以使用 JUC 提供的 AtomicReference [原子引用类] 将多个变量组合成一个对象后再进行原子 “引用” 对象操作。
 * 3）无效 “自旋” 会造成严重的 CPU 开销问题。
 * - 解决办法：“以空间换时间”，或者排队争抢线程，或者分散竞争热点，或者使用线程本地变量。
 * --> 排队争抢线程，使用 JUC 提供的 AQS 同步组件，将发生 CAS 争抢的线程加入到一个排队队列中进行等待，降低 CAS 争抢的激烈程度；
 * --> 分散竞争热点，使用 JUC 提供的 LongAdder 替换 AtomicLong，分散竞争热点；
 * --> 使用线程本地变量，从根本上解决竞争问题。
 * 4. CAS 算法的应用案例：
 * 1）JUC 并发工具包：
 * - AtomicXXX 原子类，以及 LongAdder 分段计数器；
 * - JUC 显式锁。
 * - JUC 并发容器等。
 * 2）著名、开源中间件：
 * - Netty；
 * - JCTools（Java Concurrency Tools）：该工具提供了一系列非阻塞的并发数据结构，旨在弥补 JUC 的不足。当存在线程争抢时，非阻塞的并发数据结构要比阻塞式的并发数据结构提供更好的性能。
 * - ... ...
 * 5. 面试题：
 * 1）什么是自旋锁？什么是自适应自旋锁？
 * ... ...
 */